package cz.uvn.orthopedy.client.ui.controller;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;

import cz.uvn.orthopedy.client.ApplicationController;
import cz.uvn.orthopedy.client.entity.Hall;
import cz.uvn.orthopedy.client.ui.UIUtils;
import cz.uvn.orthopedy.shared.FieldVerifier;

public class HallsController implements PanelController, ClickHandler {
	
	public static final String[] TABLE_HEADER = {"Number", "Description", "Edit", "Remove"}; 
	
	private ApplicationController controller;
	
	private VerticalPanel panel;
	private FlexTable table;
	private Button addButton;

	public HallsController(ApplicationController controller) {
		this.controller = controller;
		initUI();
	}

	private void initUI() {
		panel = new VerticalPanel();
		panel.setHorizontalAlignment(VerticalPanel.ALIGN_RIGHT);

		table = new FlexTable();
		table.addStyleName("table");
		initTable(0);
		panel.add(table);
		
		addButton = new Button("Add...");
		addButton.addClickHandler(this);
		panel.add(addButton);
	}

	@Override
	public Panel getView() {
		return panel;
	}
	
	@Override
	public void refresh() {
		load();
	}

	@Override
	public void onClick(ClickEvent event) {
		Object source = event.getSource();
		if (source == addButton) {
			showEditDialog(null);
		}
	}
	
	private void initTable(int rows) {
		table.clear(true);
		table.setSize(String.valueOf(TABLE_HEADER.length), String.valueOf(rows + 1));
		table.setCellPadding(TABLE_HEADER.length);
		for (int i = 0; i < TABLE_HEADER.length; i++) {
			table.setText(0, i, TABLE_HEADER[i]);
		}
		table.getRowFormatter().addStyleName(0, "tableHeader");
	}
	
	private void displayHalls(final Hall[] halls) {
		initTable(halls.length);
		for (int i = 0; i < halls.length; i++) {
			final Hall hall = halls[i];
			table.setText(i + 1, 0, String.valueOf(hall.getNumber()));
			table.setText(i + 1, 1, hall.getDescription());
			
			Button editButton = new Button("...");
//			editButton.addStyleDependentName("edit");
			editButton.addClickHandler(new ClickHandler() {
				public void onClick(ClickEvent event) {
					showEditDialog(hall);
				}
			});
			table.setWidget(i + 1, 2, editButton);
			
			Button removeButton = new Button("x");
//			removeButton.addStyleDependentName("remove");
			removeButton.addClickHandler(new ClickHandler() {
				public void onClick(ClickEvent event) {
					remove(hall);
				}
			});
			table.setWidget(i + 1, 3, removeButton);
		}
	}

	private void showEditDialog(final Hall hall) {
		final DialogBox dialogBox = new DialogBox();
//		dialogBox.setWidth("200px");
//		dialogBox.addStyleName("dialogBox");
		dialogBox.setText(hall == null ? "Add new Hall" : "Edit Hall");
		dialogBox.setAnimationEnabled(true);
		
		final TextBox numberTextBox = new TextBox();
		final TextBox descriptionTextBox = new TextBox();
		
		if (hall != null) {
			numberTextBox.setText(String.valueOf(hall.getNumber()));
			descriptionTextBox.setText(hall.getDescription());
		}

		final Button okButton = new Button("OK");
		okButton.getElement().setId("dialogButton");
		okButton.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				String numberTxt = numberTextBox.getText();
				final int number = FieldVerifier.getNumber(numberTxt);
				if (number < 0) {
					// TODO error label
					Window.alert("Incorrect number!");
					return;
				}
				if (hall == null) {
					for (Hall h : controller.getHallsCache()) {
						if (h.getNumber() == number) {
							Window.alert("Hall with such number is already exists!");
							return;
						}
					}
				}
				
				String description = descriptionTextBox.getText();
				
				if (hall == null) {
					Hall h = new Hall();
					h.setNumber(number);
					h.setDescription(description);
					edit(h);
				} else {
					hall.setNumber(number);
					hall.setDescription(description);
					edit(hall);
				}
				dialogBox.hide();
			}
		});

		final Button cancelButton = new Button("Cancel");
		cancelButton.getElement().setId("dialogButton");
		cancelButton.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				dialogBox.hide();
			}
		});

		VerticalPanel dialogVPanel = new VerticalPanel();
		dialogVPanel.addStyleName("dialogVPanel");
		dialogVPanel.add(new HTML("<b>Number:</b>"));
		dialogVPanel.add(numberTextBox);
		dialogVPanel.add(new HTML("<br><b>Description:</b>"));
		dialogVPanel.add(descriptionTextBox);

		dialogVPanel.setHorizontalAlignment(VerticalPanel.ALIGN_RIGHT);
		HorizontalPanel dialogHPanel = new HorizontalPanel();
		dialogHPanel.add(okButton);
		dialogHPanel.add(cancelButton);
		dialogVPanel.add(dialogHPanel);
		
		dialogBox.setWidget(dialogVPanel);
		dialogBox.center();
		numberTextBox.setFocus(true);
	}

	private void load() {
		controller.getJournalService().getHalls(new AsyncCallback<Hall[]>() {
			@Override
			public void onSuccess(final Hall[] halls) {
				displayHalls(halls);
			}
			@Override
			public void onFailure(Throwable error) {
				UIUtils.handleError(error);
			}
		});
	}
	
	private void edit(final Hall hall) {
		if (hall.getId() == null) {
			controller.getJournalService().createHall(hall, new AsyncCallback<Void>() {
				@Override
				public void onSuccess(Void ignore) {
					load();
				}
				@Override
				public void onFailure(Throwable error) {
					UIUtils.handleError(error);
				}
			});
		} else {
			controller.getJournalService().editHall(hall, new AsyncCallback<Void>() {
				@Override
				public void onSuccess(Void ignore) {
					load();
				}
				@Override
				public void onFailure(Throwable error) {
					UIUtils.handleError(error);
				}
			});
		}
	}

	private void remove(final Hall hall) {
		controller.getJournalService().deleteHall(hall, new AsyncCallback<Void>() {
			@Override
			public void onSuccess(Void ignore) {
				load();
			}
			@Override
			public void onFailure(Throwable error) {
				UIUtils.handleError(error);
			}
		});
	}
}
